home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 October / CHIP Turkiye Ekim 2000.iso / prog / naps / 04 / setup.exe / Gnucleus / ViewTransfer.cpp < prev    next >
C/C++ Source or Header  |  2000-07-15  |  32KB  |  1,080 lines

  1. /********************************************************************************
  2.  
  3.     Gnucleus - A node application for the Gnutella network
  4.     Copyright (C) 2000 John Marshall
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.     For support, questions, comments, etc...
  20.     E-Mail: 
  21.         swabby@c0re.net
  22.     
  23.     Address:
  24.         21 Cadogan Way
  25.         Nashua, NH, USA 03062
  26.  
  27. ********************************************************************************/
  28.  
  29. // ViewTransfer.cpp : implementation file
  30. //
  31.  
  32. #include "stdafx.h"
  33. #include "Gnucleus.h"
  34. #include "MainFrm.h"
  35.  
  36. #include "GnucleusDoc.h"
  37. #include "ViewSearch.h"
  38.  
  39. #include "GnuTransfer.h"
  40. #include "GnuHash.h"
  41. #include "GnuSock.h"
  42. #include "GnuControl.h"
  43.  
  44. #include "ViewTransfer.h"
  45.  
  46. #include "Base64.h"
  47.  
  48.  
  49. #ifdef _DEBUG
  50. #define new DEBUG_NEW
  51. #undef THIS_FILE
  52. static char THIS_FILE[] = __FILE__;
  53. #endif
  54.  
  55. /////////////////////////////////////////////////////////////////////////////
  56. // CViewTransfer
  57.  
  58. IMPLEMENT_DYNCREATE(CViewTransfer, CFormView)
  59.  
  60. CViewTransfer::CViewTransfer()
  61.     : CFormView(CViewTransfer::IDD)
  62. {
  63.     //{{AFX_DATA_INIT(CViewTransfer)
  64.         // NOTE: the ClassWizard will add member initialization here
  65.     //}}AFX_DATA_INIT
  66.  
  67.     UpdateRate = 0;
  68.     FiveSecs    = 0;
  69.  
  70.     m_bItemsChanged = false;
  71. }
  72.  
  73. CViewTransfer::~CViewTransfer()
  74. {
  75. }
  76.  
  77. void CViewTransfer::DoDataExchange(CDataExchange* pDX)
  78. {
  79.     CFormView::DoDataExchange(pDX);
  80.     //{{AFX_DATA_MAP(CViewTransfer)
  81.     DDX_Control(pDX, IDC_BUTTON_CANCEL_DOWN, m_CancelDown);
  82.     DDX_Control(pDX, IDC_BUTTON_CANCEL_UP, m_CancelUp);
  83.     DDX_Control(pDX, IDC_BUTTON_PAUSE, m_btnPause);
  84.     DDX_Control(pDX, IDC_STATIC_UPLOADS, m_stcUploads);
  85.     DDX_Control(pDX, IDC_STATIC_DOWNLOADS, m_stcDownloads);
  86.     DDX_Control(pDX, IDC_LIST_UPLOADS, m_lstUploads);
  87.     DDX_Control(pDX, IDC_LIST_DOWNLOADS, m_lstDownloads);
  88.     //}}AFX_DATA_MAP
  89. }
  90.  
  91.  
  92. BEGIN_MESSAGE_MAP(CViewTransfer, CFormView)
  93.     //{{AFX_MSG_MAP(CViewTransfer)
  94.     ON_WM_SIZE()
  95.     ON_WM_TIMER()
  96.     ON_BN_CLICKED(IDC_BUTTON_CANCEL_DOWN, OnButtonCancelDown)
  97.     ON_BN_CLICKED(IDC_BUTTON_CANCEL_UP, OnButtonCancelUp)
  98.     ON_BN_CLICKED(IDC_BUTTON_PAUSE, OnButtonPause)
  99.     ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_DOWNLOADS, OnItemchangedListDownloads)
  100.     //}}AFX_MSG_MAP
  101. END_MESSAGE_MAP()
  102.  
  103. /////////////////////////////////////////////////////////////////////////////
  104. // CViewTransfer diagnostics
  105.  
  106. #ifdef _DEBUG
  107. void CViewTransfer::AssertValid() const
  108. {
  109.     CFormView::AssertValid();
  110. }
  111.  
  112. void CViewTransfer::Dump(CDumpContext& dc) const
  113. {
  114.     CFormView::Dump(dc);
  115. }
  116. #endif //_DEBUG
  117.  
  118. /////////////////////////////////////////////////////////////////////////////
  119. // CViewTransfer message handlers
  120.  
  121. void CViewTransfer::OnInitialUpdate() 
  122. {
  123.     CFormView::OnInitialUpdate();
  124.     
  125.     Doc = (CGnucleusDoc *) GetDocument();
  126.  
  127.     // Initialize the list control
  128.     int offSet;
  129.  
  130.     if(m_lstDownloads.GetScrollLimit(SB_VERT))
  131.         offSet = ::GetSystemMetrics(SM_CXVSCROLL) + 3;
  132.     else
  133.         offSet = 4;
  134.  
  135.     CRect rect;
  136.     m_lstDownloads.GetWindowRect(&rect);
  137.  
  138.     m_lstDownloads.InsertColumn(0, "File", LVCFMT_LEFT,
  139.         (rect.Width() - offSet) * 2/6, 0);
  140.     m_lstDownloads.InsertColumn(1, "Bytes", LVCFMT_RIGHT,
  141.         (rect.Width() - offSet) * 1/6, 1);
  142.     m_lstDownloads.InsertColumn( 2, "Status", LVCFMT_LEFT,
  143.         (rect.Width() - offSet) * 1/6, 2);
  144.     m_lstDownloads.InsertColumn( 3, "Completed", LVCFMT_LEFT,
  145.         (rect.Width() - offSet) * 1/6, 3);
  146.     m_lstDownloads.InsertColumn( 4, "Rate", LVCFMT_RIGHT,
  147.         (rect.Width() - offSet) * 1/6, 4);
  148.  
  149.     m_lstDownloads.SetExtendedStyle(LVS_EX_FULLROWSELECT);
  150.  
  151.  
  152.     if(m_lstUploads.GetScrollLimit(SB_VERT))
  153.         offSet = ::GetSystemMetrics(SM_CXVSCROLL) + 3;
  154.     else
  155.         offSet = 4;
  156.  
  157.     m_lstUploads.GetWindowRect(&rect);
  158.     
  159.     m_lstUploads.InsertColumn(0, "File", LVCFMT_LEFT,
  160.         (rect.Width() - offSet) * 2/6, 0);
  161.     m_lstUploads.InsertColumn(1, "Bytes", LVCFMT_RIGHT,
  162.         (rect.Width() - offSet) * 1/6, 1);
  163.     m_lstUploads.InsertColumn( 2, "Status", LVCFMT_LEFT,
  164.         (rect.Width() - offSet) * 1/6, 2);
  165.     m_lstUploads.InsertColumn( 3, "Completed", LVCFMT_LEFT,
  166.         (rect.Width() - offSet) * 1/6, 3);
  167.     m_lstUploads.InsertColumn( 4, "Rate", LVCFMT_RIGHT,
  168.         (rect.Width() - offSet) * 1/6, 4);
  169.  
  170.     m_lstUploads.SetExtendedStyle(LVS_EX_FULLROWSELECT);
  171.  
  172.     // Set image lists
  173.     m_lstDownloads.SetImageList(GetSharedImageList(), LVSIL_SMALL);
  174.     m_lstUploads.SetImageList(GetSharedImageList(), LVSIL_SMALL);
  175.  
  176.     // Disable buttons
  177.     m_btnPause.EnableWindow(FALSE);
  178.     m_CancelDown.EnableWindow(FALSE);
  179.  
  180.     // Set the timer
  181.     DownloadTimer = SetTimer(1, 1000, 0);
  182.     UploadTimer = SetTimer(1, 1000, 0);
  183.  
  184.     // Resize the window so all the controls adjust properly
  185.     GetParentFrame()->GetClientRect(&rect);
  186.     OnSize(SIZE_RESTORED, rect.right - 4, rect.bottom - 4);
  187.  
  188.     // restore file list
  189.     m_ReadSavedTransfers();
  190.     
  191. }
  192.  
  193. void CViewTransfer::OnSize(UINT nType, int cx, int cy) 
  194. {
  195.     if(m_lstDownloads.m_hWnd != NULL)
  196.     {
  197.         RECT rectWnd,                
  198.                rectDownloads,    
  199.                rectUploads,      
  200.                rectStcDown,      
  201.                rectStcUp,           
  202.                rectBtnPause,     
  203.                rectBtnCancelUp,  
  204.                rectBtnCancelDown;
  205.  
  206.         GetWindowRect(&rectWnd);
  207.         m_lstDownloads.GetWindowRect(&rectDownloads);
  208.         m_lstUploads.GetWindowRect(&rectUploads);
  209.         m_stcDownloads.GetWindowRect(&rectStcDown);
  210.         m_stcUploads.GetWindowRect(&rectStcUp);
  211.         m_btnPause.GetWindowRect(&rectBtnPause);
  212.         m_CancelUp.GetWindowRect(&rectBtnCancelUp);
  213.         m_CancelDown.GetWindowRect(&rectBtnCancelDown);
  214.  
  215.         int top_lstDownloads    = rectDownloads.top    - rectWnd.top  - 2;
  216.         int left_lstDownloads   = rectDownloads.left   - rectWnd.left - 2;
  217. //        int right_lstDownloads  = rectDownloads.right  - rectDownloads.left;
  218. //        int bottom_lstDownloads = rectDownloads.bottom - rectDownloads.top;
  219.  
  220. //        int top_lstUploads      = rectUploads.top    - rectWnd.top  - 2;
  221.         int left_lstUploads     = rectUploads.left   - rectWnd.left - 2;
  222. //        int right_lstUploads    = rectUploads.right  - rectUploads.left;
  223. //        int bottom_lstUploads   = rectUploads.bottom - rectUploads.top;
  224.  
  225. //        int top_stcDown            = rectStcDown.top    - rectWnd.top  - 2;
  226. //        int left_stcDown        = rectStcDown.left   - rectWnd.left - 2;
  227. //        int right_stcDown        = rectStcDown.right  - rectStcDown.left;
  228.         int bottom_stcDown        = rectStcDown.bottom - rectStcDown.top;
  229.  
  230. //        int top_stcUp            = rectStcUp.top    - rectWnd.top  - 2;
  231.         int left_stcUp            = rectStcUp.left   - rectWnd.left - 2;
  232.         int right_stcUp            = rectStcUp.right  - rectStcUp.left;
  233.         int bottom_stcUp        = rectStcUp.bottom - rectStcUp.top;
  234.  
  235. //        int top_btnPause        = rectBtnPause.top    - rectWnd.top  - 2;
  236.         int left_btnPause        = rectBtnPause.left   - rectWnd.left - 2;
  237.         int right_btnPause        = rectBtnPause.right  - rectBtnPause.left;
  238.         int bottom_btnPause        = rectBtnPause.bottom - rectBtnPause.top;
  239.  
  240. //        int top_btnCancelUp        = rectBtnCancelUp.top    - rectWnd.top  - 2;
  241.         int left_btnCancelUp    = rectBtnCancelUp.left   - rectWnd.left - 2;
  242.         int right_btnCancelUp    = rectBtnCancelUp.right  - rectBtnCancelUp.left;
  243.         int bottom_btnCancelUp    = rectBtnCancelUp.bottom - rectBtnCancelUp.top;
  244.  
  245. //        int top_btnCancelDown    = rectBtnCancelDown.top    - rectWnd.top  - 2;
  246.         int left_btnCancelDown        = rectBtnCancelDown.left   - rectWnd.left - 2;
  247.         int right_btnCancelDown        = rectBtnCancelDown.right  - rectBtnCancelDown.left;
  248.         int bottom_btnCancelDown    = rectBtnCancelDown.bottom - rectBtnCancelDown.top;
  249.  
  250.         m_lstDownloads.MoveWindow(left_lstDownloads,  top_lstDownloads,                  cx - 17,             cy / 2 - bottom_stcDown - bottom_btnCancelDown - 25);
  251.         m_CancelDown.MoveWindow  (left_btnCancelDown, cy / 2 - 7 - bottom_btnCancelDown, right_btnCancelDown, bottom_btnCancelDown);
  252.         m_btnPause.MoveWindow    (left_btnPause,      cy / 2 - 7 - bottom_btnPause,      right_btnPause,      bottom_btnPause);
  253.  
  254.         m_stcUploads.MoveWindow(left_stcUp,       cy / 2 + 10,                 right_stcUp,       bottom_stcUp);
  255.         m_lstUploads.MoveWindow(left_lstUploads,  cy / 2 + bottom_stcUp + 10,  cx - 17,           cy / 2 - bottom_stcUp - bottom_btnCancelUp - 25);
  256.         m_CancelUp.MoveWindow  (left_btnCancelUp, cy - bottom_btnCancelUp - 8, right_btnCancelUp, bottom_btnCancelUp);
  257.  
  258.         // Resize columns
  259.         int offSet;
  260.  
  261.         if(m_lstDownloads.GetScrollLimit(SB_VERT))
  262.             offSet = ::GetSystemMetrics(SM_CXVSCROLL) + 3;
  263.         else
  264.             offSet = 4;
  265.  
  266.         CRect rect;
  267.         m_lstDownloads.GetWindowRect(&rect);
  268.  
  269.         m_lstDownloads.SetColumnWidth(0, (rect.Width() - offSet) * 2/6);
  270.         m_lstDownloads.SetColumnWidth(1, (rect.Width() - offSet) * 1/6);
  271.         m_lstDownloads.SetColumnWidth(2, (rect.Width() - offSet) * 1/6);
  272.         m_lstDownloads.SetColumnWidth(3, (rect.Width() - offSet) * 1/6);
  273.         m_lstDownloads.SetColumnWidth(4, (rect.Width() - offSet) * 1/6);
  274.  
  275.         
  276.         if(m_lstUploads.GetScrollLimit(SB_VERT))
  277.             offSet = ::GetSystemMetrics(SM_CXVSCROLL) + 3;
  278.         else
  279.             offSet = 4;
  280.  
  281.         m_lstUploads.GetWindowRect(&rect);
  282.  
  283.         m_lstUploads.SetColumnWidth(0, (rect.Width() - offSet) * 2/6);
  284.         m_lstUploads.SetColumnWidth(1, (rect.Width() - offSet) * 1/6);
  285.         m_lstUploads.SetColumnWidth(2, (rect.Width() - offSet) * 1/6);
  286.         m_lstUploads.SetColumnWidth(3, (rect.Width() - offSet) * 1/6);
  287.         m_lstUploads.SetColumnWidth(4, (rect.Width() - offSet) * 1/6);
  288.     }
  289.  
  290.     CFormView::OnSize(nType, cx, cy);
  291.     
  292. }
  293.  
  294.  
  295. void CViewTransfer::OnTimer(UINT nIDEvent) 
  296. {
  297.     int decimal, sign;
  298.  
  299.     if(nIDEvent == DownloadTimer)
  300.     {
  301.         QueryItem lstItem;
  302.  
  303.         // Turn queued downloads into active downloads, if there's room available
  304.         int ActiveDownloads = 0;
  305.         
  306.         for(int i = 0; i < m_lstDownloads.GetItemCount(); i++)
  307.             if("Downloading"          == m_lstDownloads.GetItemText(i, m_lstDownloads.GetColumnNumber("Status"))  ||
  308.                "Remotely queued"      == m_lstDownloads.GetItemText(i, m_lstDownloads.GetColumnNumber("Status")) ||
  309.                 -1                    != m_lstDownloads.GetItemText(i, m_lstDownloads.GetColumnNumber("Status")).Find("Connecting"))
  310.                 ActiveDownloads++;
  311.  
  312.         i = 0;
  313.         while(i < m_lstDownloads.GetItemCount() && (ActiveDownloads < Doc->m_MaxDownloads || Doc->m_MaxDownloads == 0))
  314.         {
  315.             if(m_lstDownloads.GetItemText(i, m_lstDownloads.GetColumnNumber("Status") ) == "Queued")
  316.             {
  317.                 m_lstDownloads.SetItemText(i, m_lstDownloads.GetColumnNumber("Status"), "Connecting");
  318.  
  319.                 GetQueryItem(i, 'D')->Connect( IPtoStr( GetQueryItem(i, 'D')->FileInfo.Host), GetQueryItem(i, 'D')->FileInfo.Port);
  320.                 GetQueryItem(i, 'D')->Status = "Connecting";
  321.  
  322.                 m_bItemsChanged = true;
  323.                     
  324.                 ActiveDownloads++;
  325.             }
  326.  
  327.             i++;
  328.         }
  329.  
  330.         // Update completed statuses
  331.         for(int row = 0; row < m_lstDownloads.GetItemCount(); row++)
  332.         {
  333.             CGnuTransfer *Item = GetQueryItem(row, 'D');
  334.  
  335.             if(!Item)
  336.             {
  337.                 RemoveRow(row, 'D');
  338.                 return;
  339.             }
  340.  
  341.             // Update Status
  342.             m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Status"), Item->Status);
  343.  
  344.             if("Downloading" == Item->Status )
  345.             {
  346.                 float NewRate = ( (float)Item->BytesCompleted - (float)Item->OldBytesCompleted ) / (float)1024;
  347.                 CString Rate = _fcvt( (NewRate + Item->OldRate) / (float) 2  , 2, &decimal, &sign );
  348.                 Rate.Insert(decimal, ".");
  349.                 m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Rate"), Rate + " KB/s");
  350.  
  351.                 Item->OldBytesCompleted = Item->BytesCompleted;
  352.                 Item->OldRate = NewRate;
  353.  
  354.                 UpdateRate = 0;
  355.  
  356.  
  357.                 // Update the percentage
  358.                 CString Percentage;
  359.                 Percentage = _fcvt((float)Item->BytesCompleted / (float)Item->FileSize * (float)100, 0, &decimal, &sign );
  360.                 
  361.                 if(Percentage == "")
  362.                     Percentage = "0";
  363.                 
  364.                 Percentage += "% )";
  365.  
  366.                 m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Completed"), CommaIze( DWrdtoStr(Item->BytesCompleted)) + "  ( " + Percentage);
  367.  
  368.             }
  369.             else if("Completed" == m_lstDownloads.GetItemText(row, m_lstDownloads.GetColumnNumber("Status")) )
  370.             {
  371.                 m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Completed"), "");
  372.                 m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Rate"), "");
  373.  
  374.                 if(Doc->m_AutoClearDL)
  375.                     RemoveRow(row, 'D');
  376.  
  377.                 m_bItemsChanged = true;
  378.             }
  379.  
  380.                 // Time out timed out items.
  381.                 /* 
  382.                     *** THIS ERRORS OUT ON COMPLETION OF A PUSHED DOWNLOAD, NO IDEA WHY
  383.                 if( Item->GetSecondsSinceLastContact() > Doc->m_TimeoutDownload )
  384.                 {
  385.                     GetQueryItem(row, 'D')->Status = "No response (paused)";
  386.                     m_bItemsChanged = true;
  387.                     GetQueryItem(row, 'D')->Pause();
  388.                 }
  389.                 */
  390.             else if(Item->Status.Find("Connecting") != -1)
  391.             {
  392.                 CString MaxDots;
  393.                 for(int i = 0; i < Doc->m_TimeoutDownload / 5; i++)
  394.                     MaxDots += ".";
  395.  
  396.                 if(Item->Status.Find(MaxDots) != -1)
  397.                 {
  398.                     Doc->GnuComm->NewPushRequest( Item->FileInfo );
  399. //                    RemoveRow(row, 'D');
  400.                     GetQueryItem(row, 'D')->Status = "Trying push";                    
  401.                 }
  402.                 
  403.                 if(FiveSecs >= 5)
  404.                 {
  405.                     Item->Status += '.';
  406.  
  407.                     FiveSecs = 0;
  408.                 }
  409.                 else
  410.                     FiveSecs++;
  411.  
  412.                 m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Rate"), "");
  413.             }
  414.             else
  415.             {
  416.                 if(Item->FileSize == Item->BytesCompleted)
  417.                     Item->Status = "Completed";
  418.  
  419.                 m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Rate"), "");
  420.             }            
  421.         }
  422.  
  423.         if(m_bItemsChanged)
  424.         {
  425.             // update saved file of statuses
  426.             m_SaveAllTransfers();
  427.  
  428.             m_bItemsChanged = false;
  429.         }
  430.  
  431.         // update the button status for when text changes.
  432.         m_UpdateDownloadButtons();
  433.  
  434.     }
  435.     if(nIDEvent == UploadTimer)
  436.     {
  437.         Doc->ActiveUploads = 0;
  438.  
  439.         for(int i = 0; i < m_lstUploads.GetItemCount(); i++)
  440.             if("Uploading" == m_lstUploads.GetItemText(i, m_lstUploads.GetColumnNumber("Status")))
  441.                 Doc->ActiveUploads++;
  442.  
  443.         for(int row = 0; row < m_lstUploads.GetItemCount(); row++)
  444.         {
  445.             CGnuTransfer *Item = GetQueryItem(row, 'U');
  446.  
  447.             if(!Item)
  448.             {
  449.                 RemoveRow(row, 'U');
  450.                 return;
  451.             }
  452.  
  453.             if("Uploading" == m_lstUploads.GetItemText(row, m_lstUploads.GetColumnNumber("Status")) )
  454.             {
  455.                 // If there's a bandwidth limitation set, allocate some
  456.                 if(Doc->m_LimitUp)
  457.                     Item->AllocBw = Doc->m_LimitUp * 1024 / Doc->ActiveUploads;
  458.                 else
  459.                     Item->AllocBw = -1;
  460.  
  461.                 // Update rate
  462.                 float NewRate = ( (float)Item->BytesCompleted - (float)Item->OldBytesCompleted ) / (float)1024;    
  463.                 CString Rate = _fcvt( (NewRate + Item->OldRate) / (float) 2 , 2, &decimal, &sign );
  464.                 Rate.Insert(decimal, ".");
  465.                 m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Rate"), Rate + " KB/s");
  466.  
  467.                 Item->OldBytesCompleted = Item->BytesCompleted;
  468.                 Item->OldRate = NewRate;
  469.  
  470.                 // Update percentage
  471.                 CString Percentage;
  472.                 Percentage = _fcvt((float)Item->BytesCompleted / (float)Item->FileSize * (float)100, 0, &decimal, &sign );
  473.                 
  474.                 if(Percentage == "")
  475.                     Percentage = "0";
  476.                 
  477.                 Percentage += "% )";
  478.  
  479.                 m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Completed"), CommaIze( DWrdtoStr(Item->BytesCompleted)) + "  ( " + Percentage);
  480.             }
  481.             else if("Completed" == m_lstUploads.GetItemText(row, m_lstUploads.GetColumnNumber("Status")) )
  482.             {
  483.                 m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Completed"), "");
  484.                 m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Rate"), "");
  485.  
  486.                 if(Doc->m_AutoClearUL)
  487.                     RemoveRow(row, 'U');
  488.             }
  489.             else
  490.                 m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Rate"), "");
  491.  
  492.             // Update Status
  493.             m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Status"), Item->Status);
  494.         }
  495.     }
  496.     
  497.     CFormView::OnTimer(nIDEvent);
  498. }
  499.  
  500. void CViewTransfer::NewDownload(QueryItem Item, SOCKET sock)
  501. {
  502.     m_bItemsChanged = true;
  503.     
  504.     Item.Handle = m_lstDownloads.GetItemCount();
  505.     Item.TransferType = 'D';
  506.  
  507.     if(!Item.Status.GetLength())    // check to see if they may be passed status
  508.         Item.Status = "Queued";
  509.  
  510.     // Setup new download with unique file name
  511.     if(Item.LocalFileName.IsEmpty())
  512.     {
  513.         CFileFind finder;
  514.         CString increment_insert;
  515.         int increment = 1;
  516.         int period_index = Item.FileName.ReverseFind(_T('.'));
  517.         Item.LocalFileName = Item.FileName;
  518.         // check to see if it exists already.
  519.         while(finder.FindFile(((CGnucleusDoc *)GetDocument())->m_DownloadDir + "\\" + Item.LocalFileName))
  520.         {
  521.             increment_insert.Format("[%u]", increment++);
  522.             // rename
  523.             Item.LocalFileName = Item.FileName;
  524.  
  525.             if(period_index == -1)        // add to end if there is no period, thus no extension.
  526.                 Item.LocalFileName += increment_insert;
  527.             else
  528.                 Item.LocalFileName.Insert( period_index, increment_insert );
  529.         }
  530.     }
  531.  
  532.     Doc->GnuComm->AddTransfer(Item, sock);
  533.  
  534.     m_lstDownloads.InsertItem(Item.Handle, "");
  535.     m_lstDownloads.SetItemText(Item.Handle, m_lstDownloads.GetColumnNumber( "File"), Item.FileName);
  536.     m_lstDownloads.SetItemText(Item.Handle, m_lstDownloads.GetColumnNumber( "Bytes"), CommaIze(DWrdtoStr(Item.Size)));
  537.     m_lstDownloads.SetItemText(Item.Handle, m_lstDownloads.GetColumnNumber( "Status"), Item.Status);
  538.  
  539.     int index = GetIconIndexFromName(Item.FileName);
  540.     if(index != -1)
  541.     {
  542.         m_lstDownloads.SetItem(Item.Handle, 0, LVIF_IMAGE, NULL, index, m_lstDownloads.GetColumnNumber("File" ) , 0, NULL);
  543.     }
  544. }
  545.  
  546. extern std::map <GUID, QueryItem, CompareGuids> g_pushList;
  547.  
  548. void CViewTransfer::NewPushDownload(std::string& pushString, SOCKET sock)
  549. {
  550.     if (pushString.size() > MAX_PATH)
  551.     {
  552.         // Hostile or buggy client, disconnect
  553.         CAsyncSocket tempSock;
  554.  
  555.         tempSock.Attach (sock);
  556.  
  557.         tempSock.Close ();
  558.  
  559.         return;
  560.     }
  561.  
  562.     DWORD  ref = 0;
  563.     TCHAR guid[40];
  564.     TCHAR fileName[MAX_PATH];
  565.     guid[0] = fileName[0] = 0;
  566.  
  567.     ::sscanf (pushString.c_str (), "GIV %d: %32s/%*s", &ref, guid);
  568.  
  569.     GUID tempGuid;
  570.  
  571.     // shield your eyes from this next code
  572.     unsigned char* tempGuidPtr = (unsigned char*) &tempGuid;
  573.     ::sscanf (guid, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  574.         &tempGuidPtr[0],
  575.         &tempGuidPtr[1],
  576.         &tempGuidPtr[2],
  577.         &tempGuidPtr[3],
  578.         &tempGuidPtr[4],
  579.         &tempGuidPtr[5],
  580.         &tempGuidPtr[6],
  581.         &tempGuidPtr[7],
  582.         &tempGuidPtr[8],
  583.         &tempGuidPtr[9],
  584.         &tempGuidPtr[10],
  585.         &tempGuidPtr[11],
  586.         &tempGuidPtr[12],
  587.         &tempGuidPtr[13],
  588.         &tempGuidPtr[14],
  589.         &tempGuidPtr[15]);
  590.  
  591.     tempGuid.Data1 ^= ref;            // We can't use the straight guid
  592.     tempGuid.Data2 ^= (ref << 1);    // just xor some of the values in the guid
  593.  
  594.     std::map <GUID, QueryItem, CompareGuids>::iterator tempIt = g_pushList.find (tempGuid);
  595.  
  596.     if (tempIt == g_pushList.end ())
  597.     {
  598.         // It appears that there are malicious hosts that send out pushes.
  599. //        ASSERT (FALSE);
  600.         CAsyncSocket tempSock;
  601.  
  602.         tempSock.Attach (sock);
  603.  
  604.         tempSock.Close ();
  605.  
  606.         return;
  607.     }
  608.  
  609.     std::string::iterator it;
  610.  
  611.     for (it = pushString.begin (); it != pushString.end (); it++)
  612.     {
  613.         if (*it == '/')
  614.         {
  615.             it++;
  616.             break;
  617.         }
  618.     }
  619.  
  620.     std::string temp;
  621.  
  622.     temp.assign (it, pushString.end ());
  623.     
  624.     QueryItem item = (*tempIt).second;
  625.  
  626.     item.FileName = temp.c_str ();
  627.     item.Index = ref;
  628.     item.Status = "Remotely queued";
  629.  
  630.     NewDownload (item, sock);
  631.  
  632.     g_pushList.erase (tempIt);    // Remove the file from the PUSH list once the transfer begins
  633.  
  634. /*
  635.     ((CGnucleusApp *) AfxGetApp())->TransferFrame->ShowWindow(SW_SHOW);
  636.     ((CGnucleusApp *) AfxGetApp())->TransferFrame->BringWindowToTop();
  637. */
  638. }
  639.  
  640. CGnuTransfer* CViewTransfer::GetQueryItem(int row, char type)
  641. {
  642.     CGnuTransfer *Item = Doc->GnuComm->GetTransfer(row, type);
  643.  
  644.     if(Item)
  645.         return Item;
  646.     else
  647.         return NULL;
  648.  
  649.     return NULL;
  650. }
  651.  
  652. void CViewTransfer::RemoveRow(int deadRow, char type)
  653. {
  654.     Doc->GnuComm->RemoveTransfer(deadRow, type);
  655.     
  656.     if(type == 'D')
  657.     {    for(int i = deadRow + 1; i < m_lstDownloads.GetItemCount(); i++)
  658.         {
  659.             if(GetQueryItem(i, 'D'))
  660.                 GetQueryItem(i, 'D')->Handle--;
  661.         }
  662.  
  663.         m_lstDownloads.DeleteItem(deadRow);
  664.     }
  665.     else
  666.     {
  667.         for(int i = deadRow + 1; i < m_lstUploads.GetItemCount(); i++)
  668.         {
  669.             if(GetQueryItem(i, 'U'))
  670.                 GetQueryItem(i, 'U')->Handle--;
  671.         }
  672.  
  673.         m_lstUploads.DeleteItem(deadRow);
  674.     }
  675.  
  676.  
  677.     m_bItemsChanged = true;
  678. }
  679.  
  680.  
  681. void CViewTransfer::OnButtonCancelDown() 
  682. // To have fun with multiple cancles and pauses go to the dialog view, get the properties
  683. // of the listbox and turn off the check on single item selection
  684. // but dont keep it like that until it works  =)
  685. {
  686.     int nItem;
  687.     POSITION pos = m_lstDownloads.GetFirstSelectedItemPosition();
  688.  
  689.     while(pos != NULL)
  690.     {
  691.         pos = m_lstDownloads.GetFirstSelectedItemPosition();    // *** Other wise it skips selections because of deleation from front ***
  692.         nItem = m_lstDownloads.GetNextSelectedItem(pos);
  693.         RemoveRow(nItem, 'D');
  694.         m_bItemsChanged = true;
  695.     }
  696. }
  697.  
  698. ////////////////////////////////////////////////////////////
  699. //! author="Nathan Brown"
  700. //
  701. //: Pauses and resumes files, depending on caption status.
  702. void CViewTransfer::OnButtonPause() 
  703. {
  704.     int nItem = -1;
  705.     POSITION pos = m_lstDownloads.GetFirstSelectedItemPosition();
  706.     CString str_item_text;
  707.     
  708.     // Same thing as above
  709.     while(pos != NULL)
  710.     {    
  711.         nItem = m_lstDownloads.GetNextSelectedItem(pos);
  712.         str_item_text = m_lstDownloads.GetItemText(nItem, m_lstDownloads.GetColumnNumber( "Status") );
  713.         
  714.         if(str_item_text.Find("Connecting") != -1 ||
  715.             str_item_text == "Remotely queued"  ||
  716.             str_item_text == "Downloading"  )
  717.         {
  718.             GetQueryItem(nItem, 'D')->Pause();
  719.         }
  720.         else
  721.         {
  722.             // this resumes the file, resetting the sock and re-useing the CGnuTransfer object,
  723.             GetQueryItem(nItem, 'D')->m_hSocket = INVALID_SOCKET;
  724.             GetQueryItem(nItem, 'D')->Create(0, SOCK_STREAM, FD_READ | FD_CONNECT | FD_CLOSE, NULL);
  725.             GetQueryItem(nItem, 'D')->Connect( IPtoStr( GetQueryItem(nItem, 'D')->FileInfo.Host), GetQueryItem(nItem, 'D')->FileInfo.Port);
  726.             GetQueryItem(nItem, 'D')->Status = "Connecting";
  727.         }
  728.     }
  729. }
  730.  
  731.  
  732. struct SaveItem
  733. {
  734.     char FileName[256];                    // path to remote file
  735.     char LocalFileName[256];            // file name in local save path.
  736.     
  737.     IP    Host;
  738.     WORD  Port;
  739.     DWORD Size;
  740.     
  741.     DWORD Speed;
  742.     DWORD Index;
  743.  
  744.     int   Handle;
  745.  
  746.     GUID  Guid;
  747. };
  748.  
  749. ////////////////////////////////////////////////////////////
  750. //! author="Nathan Brown"
  751. //
  752. //: Reads saved transfers from ini incase of crash, etc.
  753. void CViewTransfer::m_ReadSavedTransfers(void)
  754. {
  755.     if(!this)
  756.         return;
  757.     
  758.     // Filter Settings
  759.     int loop;
  760.  
  761.     CString str_file_name,
  762.             str_server_name_port;
  763.     DWORD    dw_file_size = 0;
  764.     LVFINDINFO FindInfo;
  765.     SaveItem transfer_item;
  766.  
  767.     CFileFind finder;
  768.  
  769.     for (loop = 0; ; ++loop)
  770.     {
  771.         // gather items for connections
  772.         QueryItem qi_transfer_item;
  773.         CString temp;
  774.         temp.Format ("File%2.2d", loop);
  775.  
  776.         if (GetPrivateProfileStruct ("Transfers", temp, (void *) &transfer_item, sizeof(SaveItem), ".\\Gnucleus.ini") )
  777.         {
  778.  
  779. /*        // think I got it fixed, can't use this when using different local file names
  780.             // Check to see if file is already in transfer list
  781.             FindInfo.flags = LVFI_PARTIAL|LVFI_STRING;
  782.             FindInfo.psz = &transfer_item.FileName[0];
  783.  
  784.             // some kind of weird problem lurks here, crashes dead, no explenation.
  785.             if( m_lstDownloads.FindItem(&FindInfo) != -1 )
  786.                 continue;        // file already in, may be different server, but continue
  787.  
  788.             // if not, add to list as queued.
  789. */
  790.             qi_transfer_item.FileName    = transfer_item.FileName;
  791.  
  792.             if(Doc->m_ResumeDL)
  793.                 qi_transfer_item.Status    = "Queued";
  794.             else
  795.                 qi_transfer_item.Status    = "Restored";
  796.             
  797.             qi_transfer_item.Guid        = transfer_item.Guid;
  798.             qi_transfer_item.Handle        = transfer_item.Handle;
  799.             qi_transfer_item.Host        = transfer_item.Host;
  800.             qi_transfer_item.Port        = transfer_item.Port;
  801.             qi_transfer_item.Size        = transfer_item.Size;
  802.             qi_transfer_item.Speed        = transfer_item.Speed;
  803.             qi_transfer_item.IconIndex    = 0;
  804.             qi_transfer_item.Index        = transfer_item.Index;
  805.             qi_transfer_item.Reverse    = 0;
  806.             qi_transfer_item.SortBy        = 0;
  807.  
  808.             // and last and most importantly:
  809.             qi_transfer_item.BytesCompleted = 0;
  810.             if(finder.FindFile(((CGnucleusDoc *)GetDocument())->m_DownloadDir + "\\" + transfer_item.LocalFileName))        // if it's there use the saved filesize
  811.             {
  812.                 int length = 0;
  813.                 finder.FindNextFile();
  814.                 if( (length = finder.GetLength()) )
  815.                     qi_transfer_item.BytesCompleted = length;
  816.  
  817.                 qi_transfer_item.LocalFileName = transfer_item.LocalFileName;
  818.             }
  819.             else
  820.                 qi_transfer_item.LocalFileName.Empty();
  821.  
  822.  
  823.             NewDownload(qi_transfer_item);
  824.         }
  825.         else
  826.         {
  827.             break;
  828.         }
  829.     }
  830. }
  831.  
  832. ////////////////////////////////////////////////////////////
  833. //! author="Nathan Brown"
  834. //
  835. //: Saves all transfers in ini file useing base64 encoding
  836. void CViewTransfer::m_SaveAllTransfers(void)
  837. {
  838.     // Filter Settings
  839.     int loop;
  840.  
  841.     CString str_file_name,
  842.             str_server_name_port;
  843.     CString temp_key;
  844.     SaveItem transfer_item;
  845.     QueryItem qi_transfer_item;
  846.  
  847.     // Clear out items
  848.     for (loop = 0; true; ++loop)
  849.     {
  850.         temp_key.Format ("File%2.2d", loop);
  851.  
  852.         if (GetPrivateProfileStruct("Transfers", temp_key, (void *) &transfer_item, sizeof(SaveItem), ".\\Gnucleus.ini") > 0)
  853.             WritePrivateProfileStruct ("Transfers", temp_key, NULL, sizeof(SaveItem), ".\\Gnucleus.ini");        // remove
  854.         else
  855.             break;
  856.     }
  857.  
  858.     // write out current transfers
  859.     for (loop = 0; loop < m_lstDownloads.GetItemCount(); ++loop)
  860.     {
  861.         temp_key.Format ("File%2.2d", loop);
  862.  
  863.         qi_transfer_item = GetQueryItem(loop, 'D')->FileInfo;
  864.  
  865.         strcpy(transfer_item.FileName, qi_transfer_item.FileName);
  866.         strcpy(transfer_item.LocalFileName, qi_transfer_item.LocalFileName);
  867.         transfer_item.Guid        = qi_transfer_item.Guid;
  868.         transfer_item.Handle    = qi_transfer_item.Handle;
  869.         transfer_item.Host        = qi_transfer_item.Host;
  870.         transfer_item.Port        = qi_transfer_item.Port;
  871.         transfer_item.Size        = qi_transfer_item.Size;
  872.         transfer_item.Speed        = qi_transfer_item.Speed;
  873.         transfer_item.Index        = qi_transfer_item.Index;
  874.  
  875.         WritePrivateProfileStruct ("Transfers", temp_key, (void *)&transfer_item, sizeof(SaveItem), ".\\Gnucleus.ini");
  876.         
  877.     }
  878. }
  879.  
  880. ////////////////////////////////////////////////////////////
  881. //! author="Nathan Brown"
  882. //
  883. //: Maintains correct cancel and resume/pause button status
  884. void CViewTransfer::m_UpdateDownloadButtons(void)
  885. {
  886.     if(m_lstDownloads.GetSelectedCount())
  887.     {
  888.         int n_item;
  889.         bool b_pause = false,
  890.             b_activate = false;
  891.         POSITION pos = m_lstDownloads.GetFirstSelectedItemPosition();
  892.  
  893.         while(pos)
  894.         {
  895.             n_item = m_lstDownloads.GetNextSelectedItem(pos);
  896.  
  897.             CString str_item_text = m_lstDownloads.GetItemText(n_item, m_lstDownloads.GetColumnNumber( "Status"));
  898.  
  899.             if(str_item_text.Find("Connecting") != -1 ||
  900.                 str_item_text == "Remotely queued"  ||
  901.                 str_item_text == "Downloading"  )
  902.             {
  903.                 b_pause = true;
  904.             }
  905.  
  906.             // need to make sure all possible strings that can resume are listed here.
  907.             if(str_item_text == "Paused" ||
  908.                 str_item_text == "Queued" ||
  909.                 str_item_text == "Restored" ||
  910.                 str_item_text == "Connection Refused" ||
  911.                 str_item_text == "HTTP 404 Error" ||
  912.                 str_item_text == "HTTP 200 Error" ||
  913.                 str_item_text == "Remotely Canceled" ||
  914.                 str_item_text == "Trying push" ||
  915.                 str_item_text == "Bad Header")
  916.             {
  917.                 b_activate = true;
  918.             }
  919.  
  920.             // make sure we are only going one way. disable otherwise.
  921.             if(b_activate && b_pause)
  922.             {
  923.                 m_CancelDown.EnableWindow(TRUE);    // can cancel if any selected
  924.                 m_btnPause.EnableWindow(FALSE);
  925.                 return;
  926.                 
  927.             }
  928.             
  929.         }
  930.  
  931.         m_CancelDown.EnableWindow(TRUE);
  932.         // well it all went well, so enable the button one way or the other
  933.         if(b_activate || b_pause)
  934.         {
  935.             m_btnPause.SetWindowText(b_activate ? "Activate" : "Pause" );
  936.             m_btnPause.EnableWindow(TRUE);
  937.         }
  938.         else
  939.         {
  940.             m_btnPause.EnableWindow(FALSE);
  941.         }
  942.  
  943.     }
  944.     else
  945.     {
  946.         m_CancelDown.EnableWindow(FALSE);
  947.         m_btnPause.EnableWindow(FALSE);
  948.     }
  949.  
  950. }
  951.  
  952. ////////////////////////////////////////////////////////////
  953. //! author="Nathan Brown"
  954. //
  955. //: Maintains correct cancel and resume/pause button status
  956. void CViewTransfer::OnItemchangedListDownloads(NMHDR* pNMHDR, LRESULT* pResult) 
  957. {
  958.     NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  959.     *pResult = 0;
  960.  
  961.     if( (pNMListView->uChanged & LVIF_STATE) == LVIF_STATE )
  962.     {
  963.         // Doesn't work for when the text changes, need to fix that later.
  964.         if((pNMListView->uNewState & LVIS_SELECTED) 
  965.             | (pNMListView->uOldState & LVIS_SELECTED))
  966.                 m_UpdateDownloadButtons();
  967.     }
  968.     else        // if what changed is not what we are interested in, don't worry about it.
  969.         return;
  970. }
  971.  
  972. void CViewTransfer::NewUpload(CString Header, SOCKET sock)
  973. {
  974.     // If its past the max uploads drop it
  975.     if(Doc->m_MaxUploads)
  976.         if(Doc->m_MaxUploads <= Doc->ActiveUploads)
  977.             return;
  978.  
  979.     DWORD index;
  980.     TCHAR name[256];
  981.     DWORD bytes = 0;
  982.  
  983.     ::sscanf(Header, "GET /get/%ld/%s HTTP/1.0\r\n", &index, name);
  984.     CString FileName(Header.Mid( Header.Find(name), Header.Find(" HTTP/1.0") - Header.Find(name)));
  985.  
  986.     bool found = 0;
  987.  
  988.     if(Header.Find("bytes=") != -1)
  989.     {
  990.         int pos = Header.Find("bytes=") + 6;
  991.         bytes = atol( Header.Mid(pos, Header.Find("-\r\n") - pos));
  992.         found = 1;
  993.     }
  994.  
  995.     QueryItem Item;
  996.  
  997.     if(found)
  998.         Item.BytesCompleted = bytes;
  999.     else
  1000.         Item.BytesCompleted = 0;
  1001.  
  1002.     // Find file in the list
  1003.     std::vector<SharedFile>::iterator itName;
  1004.     std::vector<DWORD>::iterator itSize;
  1005.  
  1006.     CString ShortName;
  1007.  
  1008.     DWORD loop = 0;
  1009.     for(loop = 0, itName = Doc->SharedFiles.begin(), itSize = Doc->SharedSizes.begin(); 
  1010.         itName != Doc->SharedFiles.end(), itSize != Doc->SharedSizes.end(); 
  1011.         loop++, itName++, itSize++)
  1012.     {
  1013.         if(loop == index)
  1014.             if(FileName != (*itName).FileName)
  1015.                 return;
  1016.             else
  1017.             {
  1018.                 ShortName = (*itName).FileName;
  1019.  
  1020.                 Item.FileName = (*itName).FileDir;
  1021.                 Item.Size = *itSize;
  1022.                 Item.Index = loop;
  1023.             }
  1024.     }
  1025.  
  1026.     if(index > loop)
  1027.         return;
  1028.  
  1029.     // Setup structure and list
  1030.     Item.Handle = m_lstUploads.GetItemCount();
  1031.     Item.TransferType = 'U';
  1032.     Item.Status = "Connecting";
  1033.  
  1034.  
  1035.     m_lstUploads.InsertItem(Item.Handle, "" );
  1036.     m_lstUploads.SetItemText(Item.Handle, m_lstUploads.GetColumnNumber( "File"), ShortName);
  1037.     m_lstUploads.SetItemText(Item.Handle, m_lstUploads.GetColumnNumber( "Bytes"), CommaIze(DWrdtoStr(Item.Size)));
  1038.     m_lstUploads.SetItemText(Item.Handle, m_lstUploads.GetColumnNumber( "Status"), Item.Status);
  1039.  
  1040.     int icon = GetIconIndexFromName(ShortName);
  1041.     if(icon != -1)
  1042.         m_lstUploads.SetItem(Item.Handle, 0, LVIF_IMAGE, NULL, icon, m_lstUploads.GetColumnNumber( "File"), 0, NULL);
  1043.  
  1044.     // A normal upload
  1045.     if(sock)
  1046.     {
  1047.         Doc->GnuComm->AddTransfer(Item, sock);    
  1048.         GetQueryItem(Item.Handle, 'U')->StartSending();
  1049.     }
  1050.     // A push upload
  1051.     else
  1052.     {
  1053.         CGnuTransfer *Push = GetQueryItem(16000, 'U');
  1054.  
  1055.         if(Push)
  1056.         {
  1057.             Push->FileInfo = Item;
  1058.             Push->Handle = Item.Handle;
  1059.             Push->FileSize = Item.Size;
  1060.             
  1061.             GetQueryItem(Item.Handle, 'U')->StartSending();
  1062.         }
  1063.     }
  1064.  
  1065.  
  1066. }
  1067.  
  1068. void CViewTransfer::OnButtonCancelUp()
  1069. {
  1070.     int nItem;
  1071.     POSITION pos = m_lstUploads.GetFirstSelectedItemPosition();
  1072.  
  1073.     while(pos != NULL)
  1074.     {
  1075.         pos = m_lstUploads.GetFirstSelectedItemPosition();    // *** Other wise it skips selections because of deleation from front ***
  1076.         nItem = m_lstUploads.GetNextSelectedItem(pos);
  1077.         RemoveRow(nItem, 'U');
  1078.     }
  1079. }
  1080.